// Fill out your copyright notice in the Description page of Project Settings.


#include "UserWidget/WidgetComponent/CompassWidget.h"
#include "UserWidget/WidgetComponent/SingleMarkerWidget.h"
#include "UserWidget/WidgetComponent/SingleDirectionWidget.h"
#include "Libraries/CommonLibrary.h"
#include "Libraries/GameKitFL.h"
#include "Components/Overlay.h"
#include "Components/OverlaySlot.h"
#include "Components/Image.h"
#include "Components/TextBlock.h"
#include "Components/Border.h"
#include "Components/Slider.h"

void UCompassWidget::NativePreConstruct() {
	Super::NativePreConstruct();
	SpecialAreaVisibility = EToggleVisibility::Hidden;
	SpecialAreaTextVisibility= EToggleVisibility::Visible;
	SpecialAreaInBrushColor = FLinearColor(0.f, 0.f, 0.f, 0.f);
	ColorAlphaChange = 0.f;
}

USingleDirectionWidget* UCompassWidget::AddDirection(const FDirections& Direction, TSubclassOf<USingleDirectionWidget> DirectionWidgetClass)
{
	USingleDirectionWidget* LocWidgetReference = CreateWidget<USingleDirectionWidget>(this, DirectionWidgetClass);
	if (!LocWidgetReference) {
		CZ_LOG_S(FString("UCompassWidget"), FString("Create Direction Widget Object Fail"));
		DEBUG_MESSAGE("Create Direction Widget Object Fail");
		return nullptr;
	}
	LocWidgetReference->ContructWidget(Direction);
	DirectionWidgets.Add(LocWidgetReference);
	UOverlaySlot* TempSlot = DirectionOverlay->AddChildToOverlay(LocWidgetReference);
	TempSlot->SetHorizontalAlignment(EHorizontalAlignment::HAlign_Center);
	TempSlot->SetVerticalAlignment(EVerticalAlignment::VAlign_Bottom);
	return LocWidgetReference;
}

USingleMarkerWidget* UCompassWidget::AddMarker(FTargetInfo LocTargetInfo,TSubclassOf< USingleMarkerWidget> MarkerWidgetClass)
{
	USingleMarkerWidget* LocWidgetRef = CreateWidget<USingleMarkerWidget>(this,MarkerWidgetClass);
	if (!LocWidgetRef) {
		CZ_LOG_S(FString("UCompassWidget"), FString("Create Marker Widget Object Fail"));
		DEBUG_MESSAGE("Create Marker Widget Object Fail");
		return nullptr;
	}
	LocWidgetRef->ConstructWidget(LocTargetInfo);
	switch (LocTargetInfo.MarkerCustomization.MarkerType)
	{
	case EMarkerType::ScreenMarker:
		ScreenMarkers.Add(LocWidgetRef);
		LocWidgetRef->AddToViewport();
		break;
	case EMarkerType::CompassMarker:
		LocWidgetRef->SetVisibility(ESlateVisibility::Collapsed);
		CompassMarkers.Add(LocWidgetRef);
		{
			UOverlaySlot* TempSlot = CompassMarkerOverlay->AddChildToOverlay(LocWidgetRef);
			TempSlot->SetHorizontalAlignment(EHorizontalAlignment::HAlign_Center);
			TempSlot->SetVerticalAlignment(EVerticalAlignment::VAlign_Center); 
		}
		break;
	case EMarkerType::None:
		HiddenMarkers.Add(LocWidgetRef);
		break;
	default:
		break;
	}
	return LocWidgetRef;
}

void UCompassWidget::ToggleCompassVisibility(EToggleVisibility INVisibility)
{

}

USingleMarkerWidget* UCompassWidget::AddLandmark(FMarkerCustomization MarkerCustomization, TSubclassOf<USingleMarkerWidget> MarkerWidgetClass)
{
	USingleMarkerWidget* LocWidgetRef = CreateWidget<USingleMarkerWidget>(this, MarkerWidgetClass);
	if (!LocWidgetRef) {
		CZ_LOG_S(FString("UCompassWidget"), FString("Create Marker Widget Object Fail"));
		DEBUG_MESSAGE("Create Marker Widget Object Fail");
		return nullptr;
	}
	FTargetInfo TempParm = FTargetInfo();
	TempParm.MarkerCustomization = MarkerCustomization;
	LocWidgetRef->ConstructWidget(TempParm);
	LocWidgetRef->Indicator->SetVisibility(ESlateVisibility::Hidden);
	LocWidgetRef->Distance->SetVisibility(ESlateVisibility::Hidden);
	Landmarks.Add(LocWidgetRef);
	UOverlaySlot* TempSlot = CompassMarkerOverlay->AddChildToOverlay(LocWidgetRef);
	TempSlot->SetHorizontalAlignment(EHorizontalAlignment::HAlign_Center);
	TempSlot->SetVerticalAlignment(EVerticalAlignment::VAlign_Center);
	return LocWidgetRef;
}

void UCompassWidget::UpdateSpecialArea(EToggleVisibility HighlightVisibility, EToggleVisibility TextVisibility, FLinearColor InBrushColor, FText InText)
{
	if (HighlightVisibility != SpecialAreaVisibility) {
		SpecialAreaVisibility = HighlightVisibility;
		SpecialAreaTextVisibility = TextVisibility;
		SpecialAreaInBrushColor = InBrushColor;
		CompassText->SetText(InText);
		DynamicBackground->SetBrushColor(SpecialAreaInBrushColor);
		TextBackground->SetBrushColor(SpecialAreaInBrushColor);
		Background->SetBrushColor(SpecialAreaInBrushColor);
		SliderFade->SetSliderHandleColor(SpecialAreaInBrushColor);
		CompassTextOverlay->SetVisibility(SpecialAreaTextVisibility == EToggleVisibility::Hidden ? ESlateVisibility::Hidden : ESlateVisibility::SelfHitTestInvisible);
		UWidgetAnimation* SpecialAreaAnim = UCommonLibrary::GetAnimInstance(GetClass(), FText::FromString("SpecialAreaAnim"));
		if (SpecialAreaAnim) {
			PlayAnimation(SpecialAreaAnim, UGameKitFL::CalculateAnimationCurrentTime(this, SpecialAreaAnim), 1.f, SpecialAreaVisibility == EToggleVisibility::Hidden ? EUMGSequencePlayMode::Reverse : EUMGSequencePlayMode::Forward);
		}
		FTimerDelegate RespawnDelegate = FTimerDelegate::CreateUObject(this, &UCompassWidget::ClearTimer);
		GetWorld()->GetTimerManager().SetTimer(HighlightTimerHandle, RespawnDelegate, 0.01, true);
	}
}

void UCompassWidget::UpdateCompassColor()
{
	switch (SpecialAreaVisibility) {
	case EToggleVisibility::Visible:
		CompassVisibleColor();
		break;
	case EToggleVisibility::Hidden:
		CompassHiddenColor();
		break;
	default:
		break;
	}
}

void UCompassWidget::CompassVisibleColor() {
	ColorAlphaChange = FMath::Clamp(ColorAlphaChange + 0.01f, 0.f, 1.f);
	Compass->SetBrushColor(FMath::Lerp<FLinearColor>(FLinearColor(1.f, 1.f, 1.f, 1.f), SpecialAreaInBrushColor, ColorAlphaChange));
	SliderFade->SetSliderHandleColor(FLinearColor(SpecialAreaInBrushColor.R, SpecialAreaInBrushColor.G, SpecialAreaInBrushColor.B, 0.f));
	ClearHighlightTimer();
}

void UCompassWidget::CompassHiddenColor() {
	ColorAlphaChange = FMath::Clamp(ColorAlphaChange - 0.01f, 0.f, 1.f);
	Compass->SetBrushColor(FMath::Lerp<FLinearColor>(FLinearColor(1.f, 1.f, 1.f, 1.f), SpecialAreaInBrushColor, ColorAlphaChange));
	SliderFade->SetSliderHandleColor(FLinearColor(1.f,1.f,1.f, 0.f));
	DynamicBackground->SetBrushColor(FLinearColor(1.f, 1.f, 1.f, 0.f));
	if (Compass->GetBrushColor().R == 1.f && Compass->GetBrushColor().G == 1.f && Compass->GetBrushColor().B == 1.f) {
		ClearHighlightTimer();
	}
}

void UCompassWidget::ClearHighlightTimer() {
	if (UniqueHandle.IsValid()) {
		GetWorld()->GetTimerManager().ClearTimer(UniqueHandle);
	}
	FTimerDelegate RespawnDelegate = FTimerDelegate::CreateUObject(this, &UCompassWidget::ClearTimer);
	GetWorld()->GetTimerManager().SetTimer(UniqueHandle, RespawnDelegate, 2.f, false);
}

void UCompassWidget::ClearTimer() {
	if (HighlightTimerHandle.IsValid()) {
		GetWorld()->GetTimerManager().ClearTimer(HighlightTimerHandle);
	}
}
